package com.cy.cy2025.util

import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import com.cy.cy2025.MyApplication
import com.google.gson.Gson
import java.io.File
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException


object SpUtil {

    /**
     * 格式化key，对key进行md5处理后转为16进制字符串
     */
    private fun getMd5Key(key: String): String {
        try {
            // 创建MD5消息摘要实例
            val md = MessageDigest.getInstance("MD5")
            // 更新摘要信息
            md.update(key.toByteArray())
            // 获取哈希值字节数组
            val digest = md.digest()
            // 将字节数组转换为十六进制字符串
            val sb = StringBuilder()
            for (b in digest) {
                // 转换为两位十六进制数
                val hex = Integer.toHexString(0xFF and b.toInt())
                if (hex.length == 1) {
                    sb.append('0')
                }
                sb.append(hex)
            }
            return sb.toString()
        } catch (e: NoSuchAlgorithmException) {
            // 理论上不会发生，因为MD5是标准算法
            e.printStackTrace()
            return key
        }
    }
    
    private fun getSp(key: String): SharedPreferences =
        MyApplication.app.getSharedPreferences(key, Context.MODE_PRIVATE)

    fun put(key: String, value: Any) {
        when (value) {
            is String -> putString(key, value)
            is Int -> putInt(key, value)
            is Long -> putLong(key, value)
            is Boolean -> putBoolean(key, value)
            is Float -> putFloat(key, value)
            else -> putObject(key, value)
        }
    }

    inline fun <reified T> get(key: String): T? {
        when (T::class.java) {
            String::class.java -> return getString(key) as T
            Int::class.java -> return getInt(key, 0) as T
            Long::class.java -> return getLong(key, 0L) as T
            Boolean::class.java -> return getBoolean(key, false) as T
            Float::class.java -> return getFloat(key, 0f) as T
        }
        return getObject(key, T::class.java)
    }


    fun putObject(key: String, value: Any) {
        val formatKey = getMd5Key(key)
        getSp(formatKey).edit(true) { putString(formatKey, Gson().toJson(value)) }
    }

    fun <T> getObject(key: String, clazz: Class<T>): T? {
        val formatKey = getMd5Key(key)
        return runCatching {
            Gson().fromJson<T>(getSp(formatKey).getString(formatKey, null), clazz)
        }.onFailure {
            LogUtil.e("SpUtil", "getObject error:${it.message}")
        }.getOrNull()

    }

    fun putString(key: String, value: String) {
        val formatKey = getMd5Key(key)
        getSp(formatKey).edit(true) { putString(formatKey, value) }
    }

    fun getString(key: String): String? {
        val formatKey = getMd5Key(key)
        return getSp(formatKey).getString(formatKey, null)
    }

    fun putInt(key: String, value: Int) {
        val formatKey = getMd5Key(key)
        getSp(formatKey).edit(true) { putInt(formatKey, value) }
    }

    fun getInt(key: String, defValue: Int): Int {
        val formatKey = getMd5Key(key)
        return getSp(formatKey).getInt(formatKey, defValue)
    }

    fun putLong(key: String, value: Long) {
        val formatKey = getMd5Key(key)
        getSp(formatKey).edit(true) { putLong(formatKey, value) }
    }

    fun getLong(key: String, defValue: Long): Long {
        val formatKey = getMd5Key(key)
        return getSp(formatKey).getLong(formatKey, defValue)
    }

    fun putBoolean(key: String, value: Boolean) {
        val formatKey = getMd5Key(key)
        getSp(formatKey).edit(true) { putBoolean(formatKey, value) }
    }

    fun getBoolean(key: String, defValue: Boolean): Boolean {
        val formatKey = getMd5Key(key)
        return getSp(formatKey).getBoolean(formatKey, defValue)
    }

    fun putFloat(key: String, value: Float) {
        val formatKey = getMd5Key(key)
        getSp(formatKey).edit(true) { putFloat(formatKey, value) }
    }

    fun getFloat(key: String, defValue: Float): Float {
        val formatKey = getMd5Key(key)
        return getSp(formatKey).getFloat(formatKey, defValue)
    }

    fun remove(key: String) {
        val formatKey = getMd5Key(key)
        getSp(formatKey).edit(true) { remove(formatKey) }
    }


    /**
     * 清除所有数据
     */
    fun clearAll() {
        try {
            // 获取SharedPreferences的文件目录
            val prefsDir = File(MyApplication.app.dataDir.path + "/shared_prefs")
            if (prefsDir.exists() && prefsDir.isDirectory) {
                prefsDir.listFiles()?.forEach {
                    val spName = it.name.substring(0, it.name.lastIndexOf("."))
                    if (!MyApplication.app.deleteSharedPreferences(spName)){
                        if (!it.delete()) {
                            getSp(spName).edit(true) { clear() }
                        }
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


}